#include "imageprovider.h"
#include "imagerecord.h"
#include "logger.h"



ImageRecord::ImageRecord()
    :  isSkipDisplay_(false),lastTime(0),m_timesCapture(0), m_timesReprogress(0), m_timesDetect(0),
    m_timesCv(0),m_timesSummary(0),m_timesFinal(0),m_ID(-1),m_state(State::Running)
// m_stateRunning(&m_stateMachine), m_stateSucceed(&m_stateMachine),
// m_stateFail(&m_stateMachine)
{

    detectStepTime.clear();
    detectStepTime["Capture"] = 0;
    detectStepTime["Reprogress"] = 0;
    detectStepTime["Detect"] = 0;
    detectStepTime["Cv"] = 0;
    detectStepTime["Summary"] = 0;
    detectStepTime["Other"] = 0;
    detectStepTime["PCcore"] = 0;
    detectStepTime["Total"] = 1;


    detectStepInfo["Reprogress"] = "";
    detectStepInfo["Detect"] = "";
    detectStepInfo["Cv"] = "";
    m_timer.start();
    initializeStateMachine();
}

void ImageRecord::initializeStateMachine() {
    // connect(&m_stateRunning, &QState::entered, [this](){ logStateChange(State::Running); });
    // connect(&m_stateSucceed, &QState::entered, [this](){ logStateChange(State::Succeed); });
    // connect(&m_stateFail, &QState::entered, [this](){ logStateChange(State::Fail); });

    // m_stateMachine.addState(&m_stateRunning);
    // m_stateMachine.addState(&m_stateSucceed);
    // m_stateMachine.addState(&m_stateFail);
    // m_stateMachine.setInitialState(&m_stateRunning);
    // m_stateMachine.start();
}

void ImageRecord::logStateChange(State state) {
    switch (state) {
    case State::Running:
        LogDebug << "State changed to Running";
        break;
    case State::Succeed:
        LogDebug << "State changed to Succeed";
        break;
    case State::Fail:
        LogDebug << "State changed to Fail";
        break;
    }
}

void ImageRecord::setStepImage(StepProcess step, const cv::Mat& image, DisplayImgStep displayStep ) {
    // if (image.empty()) {
    //     //LogWarning << "Fail setStepImage because image is empty";
    //     //setState(State::Fail);
    //     return;
    // }
    displayStep_ = displayStep;
    m_endStepLast = step;
    int currentTime = m_timer.elapsed();
    LogTrack << "Curreat Time " << currentTime;
    switch (step) {
    case StepProcess::Capture:
        m_originalImage = image; //原图不保存
        m_timesCapture = currentTime - lastTime;
        break;
    case StepProcess::Reprogress:
        m_reprogressImage = image.clone();
        m_timesReprogress = currentTime - lastTime;
        break;
    case StepProcess::Detect:
        m_detectImage = image.clone();
        m_timesDetect = currentTime - lastTime;
        break;
    case StepProcess::Cv:
        m_cvImage = image.clone();
        m_timesCv = currentTime - lastTime;
        break;
    case StepProcess::Summary:
        m_outputImage = image.clone();
        m_timesSummary = currentTime - lastTime;
        break;
    case StepProcess::PCcoreStep:
        m_outputImage = image.clone();
        m_PCcore = currentTime - lastTime;
        break;
    }


    lastTime = currentTime;
}
cv::Mat ImageRecord::getStepImage(StepProcess step) const {
    switch (step) {
    case StepProcess::Capture:
        return m_originalImage;
    case StepProcess::Reprogress:
        return m_reprogressImage;
    case StepProcess::Detect:
        return m_detectImage;
    case StepProcess::Cv:
        return m_cvImage;
    case StepProcess::PCcoreStep:
        return m_outputImage;
    case StepProcess::Summary:
        return m_outputImage;
    }
    return cv::Mat();
}

QString ImageRecord::logOutResult() {
    int all_time=m_timer.elapsed();
    QString summary = "Total Time: " + QString::number(m_timer.elapsed()) + " ms\n";

    auto appendStepTime = [&](const QString& stepName, int stepTime) {
        if (stepTime > 0) {
            double percentage = static_cast<double>(stepTime) / all_time * 100;
            summary += QString("%1 Time: %2 ms (%3%)\n")
                           .arg(stepName)
                           .arg(stepTime)
                           .arg(percentage, 0, 'f', 2);
            detectStepTime[stepName] = stepTime;
        }
    };
    detectStepTime["Total"] = m_timer.elapsed();
    detectStepTime["Other"] = detectStepTime["Total"].toInt()
                              -detectStepTime["Capture"].toInt()
                              -detectStepTime["Reprogress"].toInt()
                              -detectStepTime["Detect"].toInt()
                              -detectStepTime["Cv"].toInt()
                              -detectStepTime["Summary"].toInt();
    ;
    appendStepTime("Capture", m_timesCapture);
    appendStepTime("Reprogress", m_timesReprogress);
    appendStepTime("Detect", m_timesDetect);
    appendStepTime("Cv", m_timesCv);
    appendStepTime("PCcore", m_PCcore);
    appendStepTime("Summary", m_timesSummary);

    LogTrack << summary;
    return summary;
}
void ImageRecord::setState(State state) {
    if (m_state != state) {
        m_state = state;
        switch (state) {
        case State::Running:
            //m_stateMachine.setInitialState(&m_stateRunning);
            break;
        case State::Succeed:
            //m_stateMachine.setInitialState(&m_stateSucceed);
            break;
        case State::Fail:
            //m_stateMachine.setInitialState(&m_stateFail);
            break;
        }
        //m_stateMachine.start();
    }
}

ImageRecord::State ImageRecord::getState() const {
    return m_state;
}

cv::Mat& ImageRecord::getResultImage() {
    return m_outputImage;
}


void ImageRecord::setIsSucceeded(bool isSucceeded) {
    if (isSucceeded && getState() != State::Fail) {
        setState(State::Succeed);
    } else {
        setState(State::Fail);
    }
    m_timesFinal = m_timer.elapsed();
    switch (m_endStepLast) {
    case StepProcess::Capture:
        m_outputImage = m_originalImage;
        break;
    case StepProcess::Reprogress:
        m_outputImage = m_reprogressImage;
        break;
    case StepProcess::Detect:
        m_outputImage = m_detectImage;
        break;
    case StepProcess::Cv:
        m_outputImage = m_cvImage;
        break;
    case StepProcess::Summary:
        m_outputImage = m_cvImage;
        break;
    case StepProcess::PCcoreStep:
        break;
    }
    logOutResult();
}

void ImageRecord::setIdentImage(cv::Mat img,cv::Rect2d roi)
{
    identImage = img.clone();
    setIdentROi(roi);
    LogTrack << "setIdentImage successful";
}

void ImageRecord::setIdentRoi2src(cv::Rect2d identRoi2src_)
{
   identRoi2src = identRoi2src_;
}


NgCard ImageRecord::getNgCard()
{
    return ngcard_;
}

void ImageRecord::setDefect(int defectKind)
{
    ngcard_.addDefect(defectKind);
}

void ImageRecord::setDetectStepTime(const StepProcess step, const QString info)
{
    if(step == Reprogress)
        detectStepInfo["Reprogress"] = info;
    else if(step == Detect)
        detectStepInfo["Detect"] = info;
    else if(step == Cv)
        detectStepInfo["Cv"] = info;
    else
        LogWarning << "fail to setDetectStepTime ";
}

void ImageRecord::setMonitorRoi(cv::Rect2d rect)
{
    monitorRoi = rect;
}

void ImageRecord::setIdentROi(cv::Rect2d rect)
{
    identRoi = rect;
}

void ImageRecord::resetTimer()
{
    m_timer.restart();
}

void ImageRecord::setCaptureImageGray(cv::Mat img)
{
    m_captureImageGray = img;
}

void ImageRecord::setidentImageGray(cv::Mat img)
{
    m_identImageGray = img.clone();
}

void ImageRecord::setIsSkipDisplay(bool isSkipDisplay)
{
    isSkipDisplay_ = isSkipDisplay;
}

void ImageRecord::setID(int id)
{
    m_ID = id;
}

void ImageRecord::setbaseImage(cv::Mat img)
{
    m_baseImage = img;
}

void ImageRecord::setdrawPreoProcessImage(cv::Mat img)
{
    m_drawPreoProcessImage = img.clone();
}

void ImageRecord::setdistanceLargeSmall(const float distanceToTop, const float distanceToBottom)
{
    distanceToTop_ = distanceToTop;
    distanceToBottom_ = distanceToBottom;
}

void ImageRecord::getdistanceLargeSmall(float &distanceToTop, float &distanceToBottom)
{
    distanceToTop = distanceToTop_;
    distanceToBottom = distanceToBottom_;
}
void ImageRecord::setReprogressImageGray(cv::Mat img)
{
    m_reprogressImageGray = img.clone();
}
